/*
 * Copyright (c) 2006, 2021, webrx.cn All rights reserved.
 *
 */
package cn.exam;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Objects;
import java.util.Random;

/**
 * <p>Project: javaseapp - ImgUtils
 * <p>Powered by webrx On 2021-08-19 11:22:50
 * <p>Created by IntelliJ IDEA
 *
 * @author webrx [webrx@126.com]
 * @version 1.0
 * @since 16
 */
public class ImgUtils {
    private String srcPath;
    private BufferedImage srcImg;
    private Graphics2D g;
    private int width;
    private int height;


    public ImgUtils() {
    }

    public ImgUtils(String srcPath) {
        this.srcPath = srcPath;
        setSrcImg(new File(srcPath));
    }

    public ImgUtils(File src) {
        setSrcImg(src);
    }

    public void setSrcImg(String srcPath) {
        setSrcImg(new File(srcPath));
    }

    public void setSrcImg(File src) {
        try {
            this.setSrcPath(src.getAbsolutePath());
            this.setSrcImg(ImageIO.read(src));
            this.width = this.getSrcImg().getWidth();
            this.height = this.getSrcImg().getHeight();
            this.setG(this.srcImg.createGraphics());
            var g = this.getG();
            g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public String getSrcPath() {
        return srcPath;
    }

    public void setSrcPath(String srcPath) {
        this.srcPath = srcPath;
    }

    public BufferedImage getSrcImg() {
        return srcImg;
    }

    public void setSrcImg(BufferedImage srcImg) {
        this.srcImg = srcImg;
    }

    public Graphics2D getG() {
        return g;
    }

    public void setG(Graphics2D g) {
        this.g = g;
    }

    public String toString() {
        return String.format("%s[width=%d,height=%d]", srcPath, width, height);
    }

    public void setWaterMaskText(String text, int pos) {
        setWaterMaskText(text, "white", pos, 35, true);
    }

    public void setWaterMaskText(String text, String color, int pos, int fontsize, boolean append) {
        //设置字体
        Font font = new Font("微软雅黑", Font.BOLD, fontsize);
        this.g.setFont(font);
        //设置文字的颜色
        this.g.setColor(getColor(color));
        //设置文字的位置
        FontMetrics fm = g.getFontMetrics();
        int w = this.srcImg.getWidth();
        int h = this.srcImg.getHeight();
        int tw = fm.stringWidth(text);
        int th = fm.getHeight();
        int ascent = fm.getAscent();
        int descent = fm.getDescent();
        float x = 0.0f;
        float y = 0.0f;
        switch (pos) {
            case 1:
                x = 0f;
                y = ascent - descent / 2;
                break;

            case 2:
                x = (w - tw) / 2;
                y = ascent - descent / 2;
                break;

            case 3:
                x = w - tw;
                y = ascent - descent / 2;
                break;

            case 4:
                x = 0f;
                y = (h - th) / 2 + ascent;
                break;

            case 5:
                x = (w - tw) / 2;
                y = (h - th) / 2 + ascent;
                break;

            case 6:
                x = w - tw;
                y = (h - th) / 2 + ascent;
                break;
            case 7:
                x = 0f;
                y = h - descent / 2;
                break;
            case 8:
                x = (w - tw) / 2;
                y = h - descent / 2;
                break;
            case 9:
                x = w - tw;
                y = h - descent / 2;
                break;
            default:
                Random rand = new Random();
                x = rand.nextFloat() * (w - tw) + 0.0f;
                y = rand.nextFloat() * ((h - descent / 2) - (ascent - descent / 2)) + (ascent - descent / 2);
                break;
        }
        this.g.drawString(text, x, y);
        this.g.dispose();
        //判断是不是原图直接添加水银文字
        if (append) {
            try {
                ImageIO.write(srcImg, srcPath.substring(srcPath.lastIndexOf(".") + 1), new File(srcPath));
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            try {
                String ext = this.srcPath.substring(this.srcPath.lastIndexOf("."));
                String srcNew = this.srcPath.replace(ext, "_text" + ext);
                ImageIO.write(srcImg, srcPath.substring(srcPath.lastIndexOf(".") + 1), new File(srcNew));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }


    public void setWaterMaskText(String text, String color, int pos, int fontsize, String f, boolean append) {
        //设置字体
        Font font = null;
        try {
            font = Font.createFont(Font.TRUETYPE_FONT, new FileInputStream(f));
            font = font.deriveFont(Font.BOLD, (float) fontsize);
        } catch (FontFormatException | IOException e) {
            e.printStackTrace();
        }
        this.g.setFont(font);

        //设置文字的颜色
        this.g.setColor(getColor(color));

        //设置文字的位置
        FontMetrics fm = g.getFontMetrics();
        int w = this.srcImg.getWidth();
        int h = this.srcImg.getHeight();
        int tw = fm.stringWidth(text);
        int th = fm.getHeight();
        int ascent = fm.getAscent();
        int descent = fm.getDescent();
        float x = 0.0f;
        float y = 0.0f;
        switch (pos) {
            case 1:
                x = 0f;
                y = ascent - descent / 2;
                break;

            case 2:
                x = (w - tw) / 2;
                y = ascent - descent / 2;
                break;

            case 3:
                x = w - tw;
                y = ascent - descent / 2;
                break;

            case 4:
                x = 0f;
                y = (h - th) / 2 + ascent;
                break;

            case 5:
                x = (w - tw) / 2;
                y = (h - th) / 2 + ascent;
                break;

            case 6:
                x = w - tw;
                y = (h - th) / 2 + ascent;
                break;
            case 7:
                x = 0f;
                y = h - descent / 2;
                break;
            case 8:
                x = (w - tw) / 2;
                y = h - descent / 2;
                break;
            case 9:
                x = w - tw;
                y = h - descent / 2;
                break;
            default:
                Random rand = new Random();
                x = rand.nextFloat() * (w - tw) + 0.0f;
                y = rand.nextFloat() * ((h - descent / 2) - (ascent - descent / 2)) + (ascent - descent / 2);
                break;
        }
        this.g.drawString(text, x, y);

        //判断是不是原图直接添加水银文字
        write(append, "_text");

    }

    public Color getColor(String color) {
        Random rand = new Random();
        Color c = switch (color) {
            case "red" -> new Color(255, 0, 0, 150);
            case "green" -> new Color(0, 255, 0, 150);
            case "blue" -> new Color(0, 0, 255, 150);
            case "orange" -> new Color(243, 143, 6, 147);
            case "purble" -> new Color(150, 7, 201, 150);
            case "black" -> new Color(5, 5, 5, 171);
            case "white" -> new Color(255, 255, 255, 171);
            default -> new Color(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256), rand.nextInt(100) + 80);
        };
        return c;
    }

    /**
     * 功能：能一个目录所有图像文件添加水印文字效果
     *
     * @param dir String
     */
    public void setWaterMaskText(String dir, String text, int pos) {
        setWaterMaskText(new File(dir), text, pos);
    }

    public void setWaterMaskText(File dir, String text, int pos) {
        for (File f : Objects.requireNonNull(dir.listFiles())) {
            if (f.isDirectory()) {
                setWaterMaskText(f, text, pos);
            } else if (f.isFile() && (f.getName().endsWith(".jpg") || f.getName().endsWith(".png") || f.getName().endsWith(".gif"))) {
                try {
                    setSrcImg(f);
                    setWaterMaskText(text, pos);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void setWaterMaskLogo(String logo, int pos, boolean append) {
        setWaterMaskLogo(new File(logo), pos, append);
    }

    public void setWaterMaskLogo(File file, int pos, boolean append) {
        try {
            var logo = ImageIO.read(file);
            int ww = logo.getWidth();
            int hh = logo.getHeight();
            int x = 0;
            int y = 0;
            switch (pos) {
                case 1 -> {
                }
                case 2 -> {
                    x = (this.width - ww) / 2;
                }
                case 3 -> {
                    y = this.width - ww;
                }
                case 4 -> {
                    y = (this.height - hh) / 2;
                }
                case 5 -> {
                    x = (this.width - ww) / 2;
                    y = (this.height - hh) / 2;
                }
                case 6 -> {
                    x = this.width - ww;
                    y = (this.height - hh) / 2;
                }
                case 7 -> {
                    y = this.height - hh;
                }
                case 8 -> {
                    x = (this.width - ww) / 2;
                    y = this.height - hh;
                }
                case 9 -> {
                    x = this.width - ww;
                    y = this.height - hh;
                }
                default -> {
                    Random rand = new Random();
                    x = rand.nextInt(this.width - ww);
                    y = rand.nextInt(this.height - hh);
                }
            }
            //设置画图的透明度 .5f透明一半
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, .5f));
            this.g.drawImage(logo, x, y, null);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //判断是不是原图直接添加水银文字
        write(append, "_logo");
    }

    public void write(boolean append, String suffix) {
        if (append) {
            try {
                ImageIO.write(srcImg, srcPath.substring(srcPath.lastIndexOf(".") + 1), new File(srcPath));
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            try {
                String ext = this.srcPath.substring(this.srcPath.lastIndexOf("."));
                String srcNew = this.srcPath.replace(ext, suffix + ext);
                ImageIO.write(srcImg, srcPath.substring(srcPath.lastIndexOf(".") + 1), new File(srcNew));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void sizeTo(int width, int height, boolean append, String suffix) {
        var dst = new BufferedImage(width, height, 1);
        var g = dst.createGraphics();
        g.drawImage(this.srcImg, 0, 0, width, height, null);
        this.setSrcImg(dst);
        write(append, suffix);
    }

    public void sizeTo(double scale, boolean append, String suffix) {
        int w = (int) (this.width * scale);
        int h = (int) (this.height * scale);
        sizeTo(w, h, append, suffix);
    }

    public void sizeTo(int width, boolean append, String suffix) {
        int height = (int) (1.0 * width / this.width * this.height);
        sizeTo(width, height, append, suffix);
    }

    public void jcrop(int x, int y, int width, int height, boolean append, String suffix) {
        //裁剪图的宽度，高度及类型
        var dst = new BufferedImage(width, height, 1);
        var g = dst.createGraphics();
        g.drawImage(this.srcImg, 0, 0, width, height, x, y, x + width, y + height, null);
        //保存裁剪后的结果
        this.setSrcImg(dst);
        write(append, suffix);
    }

}
